﻿#include "TcpServer.h"
#include <QRegularExpression>

#pragma execution_character_set("utf-8")

QMap<ComState, QString> TcpServer::mapServerStateLabel;
TcpServer::TcpServer(const QString& name, QObject *parent)
    : QObject{parent}
{
    mapServerStateLabel = {{CS_Invalid,tr("不可用")},
                           {CS_Connected,tr("连接成功")},
                           {CS_UnConnected,tr("服务端打开")}};
    mServer.reset(new QTcpServer(this));

    qRegisterMetaType<ComState>("ComState");

    connect(mServer.get(), &QTcpServer::newConnection, this, &TcpServer::onClientConnected);
    connect(mServer.get(), &QTcpServer::acceptError, this, [&](QAbstractSocket::SocketError){
        emit sigMsg("Server Error:" + mServer->errorString());
    });


}

void TcpServer::setConfig(const TcpComConfig &config)
{
    mConfig = config;
}

void TcpServer::onInit()
{
    if(mServer->isListening()){
        disconnect();
        if(mServer->listen(QHostAddress(mConfig.mLocalIP), mConfig.mLocalPort)){
            setState(CS_UnConnected);
        }
    }else{
        if(mServer->listen(QHostAddress(mConfig.mLocalIP), mConfig.mLocalPort)){
            setState(CS_UnConnected);
        }
    }

}

void TcpServer::onQuit()
{
    if(mServer->isListening()){
        disconnect();
    }
}

void TcpServer::onWrite(const QString &data)
{
    if(mConfig.mIsSendHex){
        QString str = data;
        str.remove(QRegularExpression("\\s"));
        QByteArray sendByte = QByteArray::fromHex(str.toLocal8Bit());
        writeData(sendByte);
    } else {
        writeData(data.toLatin1());
    }

}

void TcpServer::onWrite(const QByteArray &data)
{
    writeData(data);
}

void TcpServer::onConfigChanged(const TcpComConfig &config)
{
    mConfig = config;
    onInit();
}


void TcpServer::setState(const ComState &state)
{
    if(mState == state)
        return;
    mState = state;
    emit sigStateChanged(mState);
}

void TcpServer::writeData(const QByteArray &data)
{
    //判断是否开启了server
    if(!mServer->isListening())
        return;
    for(auto client : mClientList){
        qint64 reply = client->write(data);
        if(reply == -1){
            emit sigMsg(tr("<font color=\'red\'>发送失败:</font>") + client->errorString());
        }
    }
}

void TcpServer::disconnect()
{
    mServer->close();
    for(auto client : mClientList){
        client->disconnectFromHost();
        if(client->state() == QAbstractSocket::UnconnectedState){
            client->abort();
        }
    }
}

void TcpServer::onReadyRead(QTcpSocket* socket)
{
    QByteArray arrData = socket->readAll();
    emit sigReceiveData(arrData);
    processData(socket, arrData);
}

void TcpServer::processData(QTcpSocket* socket, const QByteArray &data)
{

}

void TcpServer::onClientConnected()
{
    //如果有新的连接就取出
    while(mServer->hasPendingConnections())
    {
        //nextPendingConnection返回下一个挂起的连接作为已连接的QTcpSocket对象
        //套接字是作为服务器的子级创建的，这意味着销毁QTcpServer对象时会自动删除该套接字。
        //最好在完成处理后显式删除该对象，以避免浪费内存。
        //返回的QTcpSocket对象不能从另一个线程使用，如有需要可重写incomingConnection().
        QTcpSocket *socket = mServer->nextPendingConnection();
        mClientList.append(socket);
        emit sigMsg(QString("[%1:%2] Soket Connected")
                    .arg(socket->peerAddress().toString())
                    .arg(socket->peerPort()));
        mClientListIpPort.append(QString("%1:%2")
                                     .arg(socket->peerAddress().toString())
                                     .arg(socket->peerPort()));
        emit sigClientListIpChanged(mClientListIpPort);
        //关联相关操作的信号槽
        //收到数据，触发readyRead
        connect(socket,&QTcpSocket::readyRead,[this,socket]{
            //没有可读的数据就返回
            if(socket->bytesAvailable()<=0)
                return;
            //注意收发两端文本要使用对应的编解码
            onReadyRead(socket);
        });

        //错误信息
#if QT_VERSION >= 0x060000
// Qt 6 的代码
        connect(socket, &QAbstractSocket::errorOccurred,
#else
        // Qt 5 的代码
        connect(socket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
#endif
                [this,socket](QAbstractSocket::SocketError){
            emit sigMsg(QString("[%1:%2] Soket Error:%3")
                        .arg(socket->peerAddress().toString())
                        .arg(socket->peerPort())
                        .arg(socket->errorString()));
        });

        //连接断开，销毁socket对象，这是为了开关server时socket正确释放
        connect(socket,&QTcpSocket::disconnected,[this,socket]{
            emit sigMsg(QString("[%1:%2] Soket Disonnected")
                        .arg(socket->peerAddress().toString())
                        .arg(socket->peerPort()));
            mClientListIpPort.removeOne(QString("%1:%2")
                                            .arg(socket->peerAddress().toString())
                                            .arg(socket->peerPort()));
            emit sigClientListIpChanged(mClientListIpPort);
            socket->deleteLater();
            mClientList.removeOne(socket);
        });
    }
}
